﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Net;
using System.Net.Sockets;
using UnityEngine;
using UnityEngine.Events;

namespace Script.Net
{
    public class TcpClient
    {

        public TcpClientState ClientState;
        private Socket _socket;
        private bool _isReceive;
        private UnityAction<byte[]> _onDataArriveCallback;
        public TcpClient(UnityAction<byte[]> onDataArriveCallback)
        {
            _socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            _socket.SetSocketOption(SocketOptionLevel.Tcp, SocketOptionName.NoDelay, true);
            _socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.DontLinger, true);
            ClientState = new TcpClientState(TcpConnectionState.NotConnect, TcpUseState.Idel);
            _onDataArriveCallback = onDataArriveCallback;
        }
        #region 链接相关
        public void ConnectServer(IPEndPoint target, UnityAction<ResponseInfo> connectCallback)
        {
            ClientState.SetConnectionState(TcpConnectionState.Connecting);
            _socket.BeginConnect(target, OnConnect, connectCallback);
        }
        
        private void OnConnect(IAsyncResult iar)
        {
            try
            {
                _socket.EndConnect(iar);
                TcpTransData ttd = new TcpTransData();
                _socket.BeginReceive(ttd.Buffer, 0, Const.TcpBufferSize, SocketFlags.None, EndReceiveData, ttd);
                Debug.Log("成功建立连接"+_socket.RemoteEndPoint);
                var callback = iar.AsyncState as UnityAction<ResponseInfo>;
                callback(ResponseInfo.CreateSuccess());
                ClientState.SetConnectionState(TcpConnectionState.Connected);
            }
            catch(Exception e)
            {
                Debug.LogError(e);
                ClientState.SetConnectionState(TcpConnectionState.NotConnect);
            }
        }
        #endregion
        
        
        /// <summary>
        /// 结束接受数据回调
        /// </summary>
        private void EndReceiveData(IAsyncResult ar)
        {
            var ttd = ar.AsyncState as TcpTransData;
            
            int readLen = _socket.EndReceive(ar);
            if (readLen > 0)
            {
                if (ttd.Read(readLen))
                {
                    _onDataArriveCallback.Invoke(ttd.Data);
                    ttd.Reset();
                }

                _socket.BeginReceive(ttd.Buffer, 0, Const.TcpBufferSize, 0, EndReceiveData, ttd);
            }
            else
            {
                Debug.LogError("服务端Socket断开");
            }
        }

        public void SendData(byte[] data, UnityAction<ResponseInfo> callback)
        {
            ClientState.SetUseState(TcpUseState.MessageSending);
            _socket.BeginSend(data, 0, data.Length, SocketFlags.None, EndSendData, callback);
            ClientState.SetUseState(TcpUseState.Idel);
        }
        
        /// <summary>
        /// 结束发送数据回调
        /// </summary>
        /// <param name="ar"></param>
        private void EndSendData(IAsyncResult ar)
        {
            try
            {
                _socket.EndSend(ar);
                var callback = ar.AsyncState as UnityAction<ResponseInfo>;
                callback(ResponseInfo.CreateSuccess());
            }
            catch (Exception e)
            {
                Debug.LogError(e);
            }
        }

        public void Close()
        {
            _socket.Shutdown(SocketShutdown.Both);
            _socket.Close();
        }
    }
}